import {
  Component,
  Input,
  AfterViewInit,
  ViewEncapsulation,
  ChangeDetectionStrategy,
  ContentChildren,
  QueryList,
  ElementRef,
  OnChanges,
  SimpleChanges,
  ChangeDetectorRef,
} from '@angular/core';
import { InputBoolean, LvConfig, LvFormLayoutType } from '../core/api';
import { FormLabelComponent } from './form-label.component';
import { FormControlComponent } from './form-control.component';

@Component({
  selector: 'lv-form',
  templateUrl: './form.component.html',
  styles: [],
  encapsulation: ViewEncapsulation.None,
  changeDetection: ChangeDetectionStrategy.OnPush,
  host: {
    '[class.lv-form]': 'true',
    '[class.lv-form-large]': "lvSize === 'large'",
    '[class.lv-form-horizontal]': "lvLayout === 'horizontal'",
    '[class.lv-form-vertical]': "lvLayout === 'vertical'",
    '[class.lv-form-required-width-keep]': "lvLayout === 'vertical' && isKeepRequiredWidth",
  },
})
export class FormComponent implements OnChanges, AfterViewInit {
  // 域标签宽度,支持px,%,最大宽度
  @Input() lvLabelWidth: string | 'auto' = 'auto';

  @Input() lvSize: 'large' | 'default' = 'default';

  // 非必选是否保留宽度
  @Input() @InputBoolean() lvKeepRequiredWidth: boolean;

  // 域标签冒号
  @Input() lvLabelColon: boolean = !!LvConfig.formOptions.lvLabelColon;

  // 表单布局(label和control内容) 3.0规范表单改为上下结构
  @Input() lvLayout: LvFormLayoutType = LvConfig.formOptions.lvLayout || 'vertical';

  // 所有FormLabelComponent,包括嵌套
  @ContentChildren(FormLabelComponent, { descendants: true })
  _labelChildren: QueryList<FormLabelComponent>;

  @ContentChildren(FormControlComponent, { descendants: true })
  _controlChildren: QueryList<FormControlComponent>;

  // 垂直布局场景下，是否保持requiredWidth
  isKeepRequiredWidth: boolean;

  constructor(
    private elementRef: ElementRef,
    private cdr: ChangeDetectorRef,
  ) {}

  formLabelChange(): void {
    this.setLabelKeepRequiredWidth();
    this.setLabelColon();
    this.setLabelWidth();
  }

  ngAfterViewInit(): void {
    this.formLabelChange();

    this._labelChildren.changes.subscribe((): void => {
      this.formLabelChange();
    });
  }

  ngAfterContentInit(): void {
    if (this.lvSize === 'large') {
      this._controlChildren.forEach((item): void => {
        item.setLargeSize();
      });
    }
  }

  // 设置label宽度
  setLabelWidth(): void {
    const nodes = this._labelChildren;

    if (this.lvLabelWidth !== 'auto') {
      nodes.forEach((node): void => {
        node.elementRef.nativeElement.style.width = this.lvLabelWidth;
      });
    }
  }

  // 设置冒号
  setLabelColon(): void {
    const nodes = this._labelChildren;

    nodes.forEach((node): void => {
      if (node) {
        // 修改组件实例属性
        node.lvColon = typeof node.lvColon !== 'undefined' ? node.lvColon : this.lvLabelColon;
      }
    });

    this.cdr.markForCheck();
  }

  ngOnChanges(changes: SimpleChanges): void {
    const { lvLabelWidth, lvLabelColon } = changes;

    if (lvLabelWidth && !lvLabelWidth.firstChange) {
      this.setLabelWidth();
    }

    if (lvLabelColon && !lvLabelColon.firstChange) {
      this.setLabelColon();
    }

    // NEED_DO 后续添加lvSize变化场景
  }

  // 设置label非必选是否保留宽度
  setLabelKeepRequiredWidth(): void {
    const nodes = this._labelChildren;

    const keepRequiredWidth = nodes.some((node): boolean => node.lvRequired);

    // 修改组件实例属性
    nodes.forEach((node): void => {
      if (node.lvKeepRequiredWidth === undefined) {
        if (this.lvKeepRequiredWidth === undefined) {
          node.lvKeepRequiredWidth =
            LvConfig.formOptions.lvKeepRequiredWidth !== undefined
              ? LvConfig.formOptions.lvKeepRequiredWidth
              : keepRequiredWidth;
        } else {
          node.lvKeepRequiredWidth = this.lvKeepRequiredWidth;
        }
      }
    });

    this.isKeepRequiredWidth = nodes.some((node): boolean => node.lvKeepRequiredWidth);

    this.cdr.markForCheck();
  }
}
